using System.Windows.Forms;
using FarsiLibrary.Win;
using System;
using Nuwanda.TfsSpotlight.Shell.Proxies.Interfaces;

namespace Nuwanda.TfsSpotlight.Shell.Proxies
{
    public class TabStripProxy : ITabStrip
    {
        private ITabStripPresenter _presenter;
        private readonly FATabStrip _tabStrip;
        private readonly ControlInvoker _tabInvoker;

        public TabStripProxy(FATabStrip tabStrip)
        {
            this._tabStrip = tabStrip;
            this._tabInvoker = new ControlInvoker(tabStrip);
            this._tabStrip.TabStripItemSelectionChanged += this.OnTabStripItemChanged;
            this._tabStrip.TabStripItemClosing += this.OnTabStripItemClosing;
            this._tabStrip.MouseWheel += this.HandleTabStripScrolled;
            this._tabStrip.MouseClick += this.HandleTabStripClicked;
        }

        private void HandleTabStripClicked(object sender, MouseEventArgs e)
        {
            if (this._tabStrip.HitTest(e.Location) == HitTestResult.TabItem)
            {
                if(e.Button == MouseButtons.Middle)
                {
                    var item = this._tabStrip.GetTabItemByPoint(e.Location);
                    this._presenter.HandleTabClosing(item as ITabStripItem);
                    this._tabStrip.RemoveTab(item);
                }
                else
                {
                    this._tabStrip.Focus();
                }
            }
        }

        public int SelectedTabIndex
        {
            get { return this._tabInvoker.RunAndReturnInControlsThread(() => this._tabStrip.Items.IndexOf(this._tabStrip.SelectedItem)); }
        }

        public int Count
        {
            get { return this._tabInvoker.RunAndReturnInControlsThread( () => this._tabStrip.Items.Count); }
        }

        private void HandleTabStripScrolled(object sender, MouseEventArgs e)
        {
            if (this._tabStrip.HitTest(e.Location) == HitTestResult.TabItem)
            {
                if(e.Delta != 0 && this._tabStrip.Items.Count > 1)
                {
                    this._presenter.HandleTabScrolled(1 * Math.Sign(e.Delta) * -1);
                }
            }
        }

        public void AttachPresenter(ITabStripPresenter presenter)
        {
            this._presenter = presenter;
        }

        private void OnTabStripItemClosing(TabStripItemClosingEventArgs e)
        {
            if (this._presenter != null && e.Item is ITabStripItem)
                this._presenter.HandleTabClosing(e.Item as ITabStripItem);
        }

        private void OnTabStripItemChanged(TabStripItemChangedEventArgs e)
        {
            if (e.ChangeType == FATabStripItemChangeTypes.SelectionChanged)
            {
                if (this._presenter != null && e.Item is ITabStripItem)
                    this._presenter.HandleSelectedTabChanged(e.Item as ITabStripItem);
            }
        }

        public void AddTabAndActivate(ITabStripItem tab)
        {
            this._tabInvoker.RunInControlsThread(
                delegate
                    {
                        if (!(tab is FATabStripItem)) return;

                        this._tabStrip.AddTab(tab as FATabStripItem, true);
                    });
        }

        public void RemoveTab(ITabStripItem tab)
        {
            this._tabInvoker.RunInControlsThread(
                delegate
                    {
                        if (!(tab is FATabStripItem)) return;

                        this._tabStrip.RemoveTab(tab as TabStripItem);
                    });
        }

        public void SelectTab(ITabStripItem tab)
        {
            this._tabInvoker.RunInControlsThread(
                delegate
                    {
                        if (!(tab is FATabStripItem)) return;

                        this._tabStrip.SelectedItem = tab as FATabStripItem;
                    });
        }

        public void SelectTab(int index)
        {
            this._tabInvoker.RunInControlsThread(
                delegate
                    {
                        if (index < 0 || index >= this.Count) return;

                        this.SelectTab(this._tabStrip.Items[index] as ITabStripItem);
                    });
        }
    }
}